package cn.didi.feidi.javabackend.server.waterdeliver.service;

import cn.didi.feidi.javabackend.mysql.jpa.exception.MyException;
import cn.didi.feidi.javabackend.mysql.jpa.hibernate.ConditionWrapper;
import cn.didi.feidi.javabackend.mysql.jpa.order.OrderUser;
import cn.didi.feidi.javabackend.mysql.jpa.waterDeliver.WaterDeTo;
import cn.didi.feidi.javabackend.mysql.jpa.waterDeliver.WaterDeliver;
import cn.didi.feidi.javabackend.server.thirdparty.mobsms.SmsWebApiKit;
import cn.didi.feidi.javabackend.server.waterdeliver.constant.message.exception.LoginConstants;
import cn.didi.feidi.javabackend.server.waterdeliver.constant.message.exception.RegisterConstants;
import cn.didi.feidi.javabackend.server.waterdeliver.dto.LoginInfo;
import cn.didi.feidi.javabackend.server.waterdeliver.dto.RegisterInfo;
import cn.didi.feidi.javabackend.server.waterdeliver.dto.SocketMessage;
import cn.didi.feidi.javabackend.server.waterdeliver.repository.OrderUserRep;
import cn.didi.feidi.javabackend.server.waterdeliver.repository.WaterDeToRep;
import cn.didi.feidi.javabackend.server.waterdeliver.repository.WaterDeliverRep;
import cn.didi.feidi.javabackend.server.waterdeliver.utils.EntityUtil;
import cn.didi.feidi.javabackend.server.waterdeliver.utils.SocketUtil;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * Created by lindanpeng on 2017/7/16.
 */
@Service
@ComponentScan(basePackages = {"cn.didi.feidi.javabackend.server.waterdeliver"})
public class WaterDeliverService {
    @Autowired
    WaterDeliverRep waterDeliverRep;
    @Autowired
    WaterDeToRep waterDeToRep;
    @Autowired
    OrderUserRep orderUserRep;

    public void register(RegisterInfo registerInfo) throws MyException,Exception{
     // waterDeliverRep.getWaterDeliverById(registerInfo.)
           if(SmsWebApiKit.sendMsg(registerInfo.getPhoneNumber(),registerInfo.getVerificationCode(),"86")!="200"){
                throw new MyException(RegisterConstants.WRONG_VERIFICATION_CODE);
            }
        WaterDeliver waterDeliver=waterDeliverRep.getByPhoneNumber(registerInfo.getPhoneNumber());
        if(null!=waterDeliver)
            throw new MyException(RegisterConstants.IS_EXISTED);
        waterDeliver= registerInfo.wrapToWaterDeliver();
        waterDeliverRep.add(waterDeliver,false);
    }

    /**
     * 验证登录
     * @param loginInfo
     * @throws MyException
     */
    public LoginInfo login(cn.didi.feidi.javabackend.server.waterdeliver.dto.LoginInfo loginInfo) throws MyException {
        WaterDeliver waterDeliver=waterDeliverRep.getByPhoneNumber(loginInfo.getPhoneNumber());
        if(null==waterDeliver)
            throw new MyException(LoginConstants.WITHOUT_USR);
        else if(!loginInfo.getPassword().equals(waterDeliver.getPassword()))
            throw new MyException(LoginConstants.WRONG_PASSWORD);
        String newToken = EntityUtil.generateToken(loginInfo);
        WaterDeTo waterDeTo=waterDeToRep.getByWaterDeliverId(waterDeliver.getWaterDeliverId());
        if(null==waterDeTo){
            waterDeTo=new WaterDeTo();
            waterDeTo.setWaterDeliverId(waterDeliver.getWaterDeliverId());
            waterDeTo.setToken(newToken);
            waterDeTo.setOnlineTime(new Date());
            waterDeTo.setImei(loginInfo.getImei());
            waterDeToRep.add(waterDeTo,false);
        }
        else{
            waterDeTo.setToken(newToken);
            waterDeTo.setOnlineTime(new Date());
            waterDeTo.setOfflineTime(null);
            waterDeTo.setImei(loginInfo.getImei());
           if(null!=waterDeTo.getOfflineTime()){
               waterDeToRep.update(waterDeTo,false);
           }
           else{
               //TODO 测试socket
               SocketMessage socketMessage=new SocketMessage();
               socketMessage.setOp(SocketMessage.MANDATORY_LOGOUT);
               socketMessage.setContent(newToken);
               socketMessage.setUid(waterDeliver.getWaterDeliverId());
               SocketUtil.sendMessage(socketMessage, "/socketMessage");
               waterDeToRep.update(waterDeTo,false);
           }
        }
        LoginInfo result=new LoginInfo();
        result.setUid(waterDeliver.getWaterDeliverId());
        result.setToken(newToken);
        return result;
    }

    public void orderTaking(String orderId, String waterDeliverId){
        OrderUser orderUser = orderUserRep.getById(orderId, true);
        orderUser.setStatus("待取货");
        orderUser.setWaterDeliverId(Integer.valueOf(waterDeliverId));
        orderUserRep.update(orderUser, true);
    }

//    public void test(Map<String, ConditionWrapper> contidionsMap){
//        Iterator<Map.Entry<String, ConditionWrapper>> iterator = contidionsMap.entrySet().iterator();
//        boolean flag = true;
//        DetachedCriteria criteria = null;
//        int count = 1;
//        String table = "table";
//        while(iterator.hasNext()){
//            Map.Entry<String, ConditionWrapper> entry = iterator.next();
//            String tableName = null;
//            if(flag){
//                flag = false;
//                criteria = DetachedCriteria.forClass(entry.getValue().getClass());
//            }
//            else{
//                tableName = table + count++;
//                criteria.createAlias(entry.getValue().getTableName(), tableName);
//            }
//            populate(criteria, entry.getValue(), tableName);
//        }
//    }
//
//    private void populate(DetachedCriteria criteria, ConditionWrapper wrapper, String tableName){
//        if(tableName == null)
//            tableName = wrapper.getTableName();
//        List<ConditionWrapper.OperationWrapper> operations = wrapper.getOperations();
//        for(ConditionWrapper.OperationWrapper operation : operations){
//            criteria.add(Restrictions.eq(tableName + "." + operation.getKey(), operation.getValue()));
//            parse(criteria, operation, tableName);
//        }
//    }
//    private void parse(DetachedCriteria criteria, ConditionWrapper.OperationWrapper operation, String tableName){
//        String op = operation.getOp();
//        switch(op){
//            case "=" : criteria.add(Restrictions.eq(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case "<" : criteria.add(Restrictions.lt(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case "<=" : criteria.add(Restrictions.le(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case ">" : criteria.add(Restrictions.gt(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case ">=" : criteria.add(Restrictions.ge(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case "like" : criteria.add(Restrictions.like(tableName + "." + operation.getKey(), operation.getValue())); break;
//            case "asc" : criteria.addOrder(Order.asc(operation.getValue())); break;
//            case "desc" : criteria.addOrder((Order.desc(operation.getValue()))); break;
//            default: break;
//    }


    public void parse(List<ConditionWrapper> conditions){
        DetachedCriteria criteria = DetachedCriteria.forClass(WaterDeliver.class);
        for(ConditionWrapper condition : conditions){
            String operation = condition.getOperation();
            switch(operation){
                case "=" : criteria.add(Restrictions.eq(condition.getKey(), condition.getValue())); break;
                case "<" : criteria.add(Restrictions.lt(condition.getKey(), condition.getValue())); break;
                case "<=" : criteria.add(Restrictions.le(condition.getKey(), condition.getValue())); break;
                case ">" : criteria.add(Restrictions.gt(condition.getKey(), condition.getValue())); break;
                case ">=" : criteria.add(Restrictions.ge(condition.getKey(), condition.getValue())); break;
                case "like" : criteria.add(Restrictions.like(condition.getKey(), condition.getValue())); break;
                case "order" :
                    switch(condition.getKey()){
                        case "asc" : criteria.addOrder(Order.asc(condition.getValue())); break;
                        case "desc" : criteria.addOrder(Order.desc(condition.getValue())); break;
                    }
                default: break;
            }
        }

    }



}
